The TADS Alternate Library
Version 2.0

Reprocessing A Command


Copyright 2000 by Kevin Forchione.
This is part of the TADS Alternate Library Authors Manual.

Introduction and Table of Contents


Reprocessing A Command

 

Infocom games suffered from a design model “flaw” with regard to reprocessing a command. This design “flaw” was later incorporated into the TADS 2 processing model. The “flaw” is apparent in the reprocessing of the previous player command through the <<again>> or <<g>> command. Both Infocom and TADS 2 repeat a player command by re-executing the disambiguated command objects.

 

Stepping In The Same River Twice

 

In practical terms what this means is that the same action is performed upon the same objects when the <<again>> command is issued. Under most circumstances this doesn’t cause a problem. But when the action changes the state of the object in such a way that a repetitive action becomes illogical then the parser tends to display messages that don’t mesh well with the reality of the game world.

 

For example:

 

Entryway

       This large, formal entryway is slightly intimidating: the walls are lined with somber portraits of gray-haired men from decades past; a medieval suit of armor, posed with battle axe at the ready, towers over a single straight-backed wooden chair. The front door leads back outside to the south. A hallway leads north.

       You see two apples here.

       Little old Joe is here, looking hungry.

 

>eat apple

That was delicious!

>g

You can't repeat that command.

 

Obviously we should be able to eat the second apple, but modesty, and the TADS 2 parser prevent us from doing so. The technical reason is because the <<g>> is actually attempting to reprocess the eat command on the same apple selected in the original player command, but that apple is no longer in the player’s scope.

 

Betwixt Cup and Lip…

 

The ideal solution to the problem consists of resubmitting the player command “eat apple” to the parser for object disambiguation and resolution prior to command execution. But obtaining the player command and storing it is not as easy as it may at first seem. An author first encounters the player command in the parser’s preparse() hook. This function provides the author with the complete player command as it was typed on the command line. But because the player can enter multiple commands upon the command line it can be difficult to determine where one command, if you will, ends and another begins.

 

The next place the player encounters the player command is in the preparseCmd() hook. At this point the player command line has been broken up into commands. But by this time the command has undergone the following transformations:

 

 

This amounts to a substantial transformation of the portion of the original player command line under examination at that given time. Given the nature of the TADS 2 parser recreating the exact original player command would require a great deal of manual parsing by the author.

 

The Alt Library Approach

 

The solution Alt achieves does not aim for an exact reproduction, but for one that is sufficiently close to the player’s original command to enough to allow for object disambiguation and resolution to occur with reasonable correctness while providing minimal impact upon the library.

 

Entryway

       This large, formal entryway is slightly intimidating: the walls are lined with somber portraits of gray-haired men from decades past; a medieval suit of armor, posed with battle axe at the ready, towers over a single straight-backed wooden chair. The front door leads back outside to the south. A hallway leads north.

       You see two apples here.

       Little old Joe is here, looking hungry.

 

>eat apple

That was delicious!

>g

That was delicious!

>g

I don't see any apple here.

 

Alt accomplishes this by using the againPCO preparse object in conjunction with the preCommand() function and Stringizer class to capture the player command from preparseCmd(), and convert it back into a player command string that approximates what the player originally entered.

 

For instance, suppose we tell Joe to sit down on the chair. This involves the following steps:

 

>Joe, sit down on the chair

 

 

 

Obviously the string we’re storing for repetition isn’t the same as what the player entered, but it is close enough that the parser will reparse the command correctly, however if the parser does have difficulty disambiguating or resolving the command objects then it might display something other than what the player entered. For example:

 

       >joe, sit down on the chair

       Joe looks at you bemusedly and leaves the room.

       >g

       I don’t see any little old Joe here.

 

Although this problem should be quite rare, there is a more serious possibility, that the input may be substantially altered by preparse(). In this case the original player command might be altered to a format that doesn’t produce the expected results when it is reconstructed and passed back to the parser. This is the case with the <<wait>> commands processed by the gameClockPPO. In this case gameClockPPO strips off the time string portion of the command, converting it to a waitTime value and storing it. This information is then concatenated with the global.cmdString before it is reprocessed. Similar manipulations are necessary where preparse() is used to remove portions of a command to be converted to game state data.